home *** CD-ROM | disk | FTP | other *** search
- /*++
-
- /* NAME
-
- /* unalias 3
-
- /* SUMMARY
-
- /* alias processing
-
- /* PROJECT
-
- /* pc-mail
-
- /* PACKAGE
-
- /* smail
-
- /* SYNOPSIS
-
- /* char **unalias(namevec)
-
- /* char **namevec;
-
- /* DESCRIPTION
-
- /* unalias() takes an array of string pointers and returns a vector
-
- /* with string pointers to their alias expansions. The resulting
-
- /* vector is in static memory.
-
- /*
-
- /* After alias expansion, all addresses are sorted and duplicate
-
- /* names are eliminated. The algorithms for alias expansion and
-
- /* duplicate elimination are case-insensitive.
-
- /*
-
- /* unalias() accesses the alias data base through the ascf ASCII
-
- /* filter.
-
- /* DIAGNOSTICS
-
- /* unalias() returns a null pointer in case of memory-allocation problems.
-
- /*
-
- /* unalias() terminates prematurely when the alias expansion has
-
- /* produced BUFSIZ recipients. This provides some defense against
-
- /* cycles in the alias data base. It is up to the caller to
-
- /* recognize this condition.
-
- /* BUGS
-
- /* The overflow/cycle detection algorithm is inelegant.
-
- /* FILES
-
- /* Alias data base in spool directory
-
- /* AUTHOR(S)
-
- /* W.Z. Venema
-
- /* Eindhoven University of Technology
-
- /* Department of Mathematics and Computer Science
-
- /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
-
- /* CREATION DATE
-
- /* Wed Apr 6 20:21:35 MET 1988
-
- /* LAST MODIFICATION
-
- /* 90/01/22 13:02:54
-
- /* VERSION/RELEASE
-
- /* 2.1
-
- /*--*/
-
-
-
- #include "defs.h"
-
- #include "hsearch.h"
-
- #include "path.h"
-
- #include "ascf.h"
-
-
-
- /* forward declarations */
-
-
-
- hidden int hash_alias();
-
- hidden void sort_alias();
-
- hidden void uniq_alias();
-
- hidden char **find_alias();
-
-
-
- /* unalias - replace aliases by their equivalents */
-
-
-
- public char **unalias(names)
-
- char **names;
-
- {
-
- static int dohash = 1; /* hash table not yet made */
-
- static char *recp[BUFSIZ + 1]; /* the result of alias expansion */
-
- char **stop = recp + BUFSIZ; /* overflow limit */
-
-
-
- if (dohash && (dohash = hash_alias())) /* build the hash table */
-
- return (0);
-
- if (stop > find_alias(names, recp, stop)) { /* build vector of addresses */
-
- sort_alias(recp); /* sort the recp list */
-
- uniq_alias(recp); /* eliminate duplicates */
-
- }
-
- return (recp);
-
- }
-
-
-
- /* hash_alias - copy alias data base to hash table */
-
-
-
- hidden int hash_alias()
-
- {
-
- register FILE *fp;
-
- char buf[BUFSIZ];
-
-
-
- /* initialize the hash table */
-
-
-
- if (hcreate(BUFSIZ) == 0)
-
- return (-1);
-
-
-
- /*
-
- * Lines in the alias data base are of the form
-
- *
-
- * <left-hand part> <right-hand part>
-
- *
-
- * where the l.h. part is an alias, and the r.h. part one or more words. Of
-
- * course, those words can be aliases. The order in which aliases are
-
- * defined is not important. The alias data base is used only after it
-
- * has been loaded into memory.
-
- *
-
- * Each l.h. part is used as the key for finding the r.h. part in the hash
-
- * table. The r.h. part is stored as a vector of pointers to strings.
-
- */
-
-
-
- if (fp = ascopen(aliases(), "r")) { /* read through ASCII filter */
-
- while (ascgets(buf, sizeof(buf), fp)) { /* read entry from alias file */
-
- register char **cpp;
-
- ENTRY e;
-
-
-
- if ((cpp = strvec(buf, ", \t\r\n")) == 0) /* split alias entry */
-
- return (-1);
-
- if ((e.key = *cpp) /* left-hand part exists */
-
- &&(e.data = (char *) (cpp + 1)) /* right-hand part exists */
-
- &&(hsearch(e, ENTER) == 0)) /* enter hash table */
-
- return (-1);
-
- }
-
- ascclose(fp);
-
- }
-
- return (0);
-
- }
-
-
-
- /* find_alias - recursively expand aliases */
-
-
-
- hidden char **find_alias(from, to, stop)
-
- char **from;
-
- register char **to;
-
- register char **stop;
-
- {
-
- register char **cpp;
-
- register ENTRY *sp;
-
- ENTRY e;
-
-
-
- /* recursively replace aliases, but don't crash in case of cycles */
-
-
-
- for (cpp = from; *cpp && (to < stop); cpp++) {
-
- e.key = *cpp;
-
- if (sp = hsearch(e, FIND)) {
-
- to = find_alias((char **) sp->data, to, stop);
-
- } else {
-
- *to++ = *cpp;
-
- }
-
- }
-
- *to = 0;
-
- return (to);
-
- }
-
-
-
- /* Istrcmp - interface between qsort and istrcmp */
-
-
-
- hidden int Istrcmp(p1, p2)
-
- char **p1,
-
- **p2;
-
- {
-
- return (istrcmp(*p1, *p2));
-
- }
-
-
-
- /* sort_alias - sort the addresses after alias substitutions */
-
-
-
- hidden void sort_alias(to)
-
- char **to;
-
- {
-
- register char **cpp;
-
- int istrcmp();
-
-
-
- /* find out length of the list */
-
-
-
- for (cpp = to; *cpp; cpp++)
-
- /* void */ ;
-
-
-
- /* sort the list */
-
-
-
- qsort((char *) to, cpp - to, sizeof(*to), Istrcmp);
-
- }
-
-
-
- /* uniq_alias - collapse sequences of identical addresses */
-
-
-
- hidden void uniq_alias(to)
-
- char **to;
-
- {
-
- register char **in = to;
-
- register char **out = to;
-
-
-
- while (*out = *in) {
-
- while (*++in && istrcmp(*out, *in) == 0) {
-
- /* void */ ;
-
- }
-
- ++out;
-
- }
-
- }
-
-